import cv2
import matplotlib.pyplot as plt
import time
import os
from .image_processor import ImageProcessor
from .object_detector import ObjectDetector
from .semantic_analyzer import SemanticAnalyzer
from .visualizer import Visualizer
from .business_applications import create_application

class VideoAnalysisSystem:
    """视频智能分析系统主类"""
    
    def __init__(self, app_type="general", api_key=None, use_llm_api=None, llm_model=None):
        """初始化视频分析系统
        
        Args:
            app_type: 应用类型 (general, security, traffic, industrial)
            api_key: OpenAI API密钥，如果为None则尝试从环境变量获取
            use_llm_api: 是否使用大语言模型API，默认为None则从环境变量获取
            llm_model: 使用的大语言模型名称，默认为None则从环境变量获取
        """
        # 从环境变量读取配置，设置参数优先级：显式参数 > 环境变量 > 默认值
        _use_llm_api = use_llm_api if use_llm_api is not None else (
            os.getenv("USE_LLM_API", "true").lower() == "true")
        _llm_model = llm_model or os.getenv("OPENAI_MODEL", "gpt-3.5-turbo")
        _api_key = api_key or os.getenv("OPENAI_API_KEY")
        
        # 初始化各个模块，在使用时创建实例
        self.image_processor = ImageProcessor()
        self.detector = ObjectDetector()
        self.semantic_analyzer = SemanticAnalyzer(api_key=_api_key, model=_llm_model, use_api=_use_llm_api)
        self.visualizer = Visualizer()
        
        # 创建业务应用
        self.application = create_application(app_type)
        self.app_type = app_type
        
        # 创建结果目录
        self.results_dir = "results"
        if not os.path.exists(self.results_dir):
            os.makedirs(self.results_dir)
        
        print(f"视频智能分析系统初始化完成，当前应用类型：{self.application.name}")
    
    def switch_application(self, app_type):
        """切换业务应用类型
        
        Args:
            app_type: 新的应用类型
        """
        self.application.stop()
        self.application = create_application(app_type)
        self.app_type = app_type
        self.application.start()
        print(f"已切换到应用类型：{self.application.name}")
    
    def process_image(self, image_path):
        """处理单张图片
        
        Args:
            image_path: 图片路径
        
        Returns:
            处理后的图像
        """
        # 读取图片
        frame = cv2.imread(image_path)
        if frame is None:
            print(f"无法读取图片: {image_path}")
            return None
        
        # 转换为RGB格式
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        
        # 使用当前业务应用处理图像
        processed_frame = self.application.process_frame(frame_rgb)
        
        # 显示结果
        plt.figure(figsize=(12, 8))
        plt.subplot(121)
        plt.title("原始图像")
        plt.imshow(frame_rgb)
        plt.axis('off')
        
        plt.subplot(122)
        plt.title(f"分析结果 ({self.application.name})")
        plt.imshow(processed_frame)
        plt.axis('off')
        
        plt.tight_layout()
        plt.show()
        
        # 保存结果
        self.visualizer.save_results(processed_frame, f"{self.app_type}_result")
        
        return processed_frame
    
    def process_video(self, video_path=None, resize_display=True, max_width=1280, max_height=720):
        """处理视频流或摄像头

        Args:
            video_path: 视频文件路径，None表示使用摄像头
            resize_display: 是否自动调整显示窗口大小
            max_width: 显示窗口的最大宽度
            max_height: 显示窗口的最大高度
        """
        # 如果没有提供视频路径，使用摄像头
        video_source = 0 if video_path is None else video_path
        
        # 配置VideoCapture参数，特别是对网络流
        cap = cv2.VideoCapture(video_source)
        
        # 为网络流设置优化参数
        if video_path is not None:
            # 设置缓冲大小
            cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
            # 设置OpenCV的FFmpeg选项
            cap.set(cv2.CAP_PROP_FPS, 30)
            
            # 如果是网络流，添加重试机制
            retries = 3
            retry_count = 0
            while not cap.isOpened() and retry_count < retries:
                retry_count += 1
                print(f"尝试连接视频流... ({retry_count}/{retries})")
                time.sleep(1)  # 等待1秒后重试
                cap = cv2.VideoCapture(video_source)
                cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
                cap.set(cv2.CAP_PROP_FPS, 30)
        
        if not cap.isOpened():
            print(f"无法打开视频源: {video_source}")
            print("提示：网络视频流可能需要FFmpeg支持，或者URL不正确")
            print("请检查您的OpenCV是否支持FFmpeg，以及视频流URL是否可访问")
            return
        
        # 启动业务应用
        self.application.start()
        
        fps = cap.get(cv2.CAP_PROP_FPS) or 30
        frame_interval = int(fps / 5)  # 每5fps处理一帧以提高性能
        frame_count = 0
        
        print(f"开始处理视频流 (应用: {self.application.name})，按'q'键退出，按's'键切换应用，按'w'键切换窗口大小")
        
        # 设置窗口调整标志
        current_resize_mode = resize_display
        
        try:
            while self.application.is_running:
                try:
                    ret, frame = cap.read()
                    if not ret:
                        # 检查是否是网络流，如果是则尝试重新连接
                        if video_path is not None:
                            print("视频流中断，尝试重新连接...")
                            # 释放当前捕获器
                            cap.release()
                            # 创建新的捕获器
                            cap = cv2.VideoCapture(video_path)
                            cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
                            cap.set(cv2.CAP_PROP_FPS, 30)
                            
                            # 等待重连
                            time.sleep(1)
                            continue
                        else:
                            # 摄像头流中断，退出循环
                            print("视频流已结束或中断")
                            break
                    
                    frame_count += 1
                    # 只处理指定间隔的帧以提高性能
                    if frame_count % frame_interval != 0:
                        cv2.imshow("原始视频流", frame)
                    else:
                        # 转换为RGB格式（用于内部处理）
                        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                        
                        # 使用当前业务应用处理图像
                        processed_frame = self.application.process_frame(frame_rgb)
                        
                        # 转换回BGR格式用于OpenCV显示
                        display_frame = cv2.cvtColor(processed_frame, cv2.COLOR_RGB2BGR)
                        
                        # 根据调整模式处理显示帧
                        if current_resize_mode:
                            # 获取原始帧的尺寸
                            h, w = display_frame.shape[:2]
                            
                            # 计算调整后的尺寸，保持原始比例
                            if w > h:
                                # 宽度优先
                                ratio = max_width / w
                                new_width = max_width
                                new_height = int(h * ratio)
                            else:
                                # 高度优先
                                ratio = max_height / h
                                new_height = max_height
                                new_width = int(w * ratio)
                            
                            # 调整帧大小
                            resized_frame = cv2.resize(display_frame, (new_width, new_height))
                            cv2.imshow(f"视频分析结果 ({self.application.name}) [调整后大小: {new_width}x{new_height}]", resized_frame)
                        else:
                            # 原始大小显示
                            h, w = display_frame.shape[:2]
                            cv2.imshow(f"视频分析结果 ({self.application.name}) [原始大小: {w}x{h}]", display_frame)
                    
                    # 键盘交互
                    key = cv2.waitKey(1) & 0xFF
                    if key == ord('q'):
                        break
                    elif key == ord('s'):
                        # 切换应用类型
                        self._switch_app_interactive()
                    elif key == ord('w'):
                        # 切换窗口大小模式
                        current_resize_mode = not current_resize_mode
                        print(f"窗口大小模式已切换为: {'自动调整' if current_resize_mode else '原始大小'}")
                        # 关闭现有窗口
                        cv2.destroyAllWindows()
                except Exception as frame_error:
                    print(f"处理帧时出错: {frame_error}")
                    # 短暂暂停后继续尝试
                    time.sleep(0.1)
                    continue
                
        except Exception as e:
            print(f"处理视频时出错: {e}")
        finally:
            # 停止业务应用
            self.application.stop()
            cap.release()
            cv2.destroyAllWindows()
            print("视频处理已结束")
    
    def _switch_app_interactive(self):
        """交互式切换应用类型"""
        print("\n请选择应用类型:")
        print("1. 通用应用")
        print("2. 安防监控应用")
        print("3. 交通监控应用")
        print("4. 工业质检应用")
        
        # 在视频处理循环中，这里使用简单的方式切换
        # 实际应用中可能需要更复杂的交互方式
        app_types = {1: "general", 2: "security", 3: "traffic", 4: "industrial"}
        
        # 简单实现：循环切换
        current_index = None
        for idx, app_type in app_types.items():
            if app_type == self.app_type:
                current_index = idx
                break
        
        # 切换到下一个应用类型
        if current_index is not None:
            next_index = current_index % len(app_types) + 1
            self.switch_application(app_types[next_index])
        else:
            # 默认切换到通用应用
            self.switch_application("general")
    
    def batch_process_images(self, image_folder):
        """批量处理文件夹中的图片
        
        Args:
            image_folder: 图片文件夹路径
        """
        if not os.path.exists(image_folder):
            print(f"文件夹不存在: {image_folder}")
            return
        
        # 获取文件夹中的所有图片
        image_extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff']
        image_files = [
            os.path.join(image_folder, f)
            for f in os.listdir(image_folder)
            if os.path.isfile(os.path.join(image_folder, f)) and 
               os.path.splitext(f)[1].lower() in image_extensions
        ]
        
        if not image_files:
            print(f"文件夹中没有找到图片: {image_folder}")
            return
        
        print(f"找到{len(image_files)}张图片，开始批量处理...")
        
        # 为批量处理创建专用目录
        batch_dir = os.path.join(self.results_dir, f"batch_{time.strftime('%Y%m%d_%H%M%S')}")
        if not os.path.exists(batch_dir):
            os.makedirs(batch_dir)
        
        # 保存原始的results_dir配置
        original_results_dir = self.visualizer.results_dir
        self.visualizer.results_dir = batch_dir
        
        try:
            # 处理每张图片
            for i, image_path in enumerate(image_files):
                print(f"处理图片 {i+1}/{len(image_files)}: {os.path.basename(image_path)}")
                self.process_image(image_path)
        finally:
            # 恢复原始配置
            self.visualizer.results_dir = original_results_dir
            
        print(f"批量处理完成，结果保存在: {batch_dir}")

# 创建系统实例的工厂函数
def create_system(app_type="general"):
    """创建视频分析系统实例
    
    Args:
        app_type: 应用类型
    
    Returns:
        视频分析系统实例
    """
    return VideoAnalysisSystem(app_type)